package com.thoughtworks.impersonator.http.record;

import org.apache.log4j.Logger;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipelineCoverage;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;

import com.thoughtworks.impersonator.http.message.HttpExchange;
import com.thoughtworks.impersonator.http.message.storage.HttpExchangeStorage;

@ChannelPipelineCoverage("one") 
class ServerConnectionHandler extends SimpleChannelUpstreamHandler {
    private final Channel clientConnection;
    private final ChannelHandlerContext clientConnectionContext;
    private final HttpExchangeStorage exchangeStorage;
    private static final Logger log = Logger.getLogger(ClientConnectionHandler.class);

    ServerConnectionHandler(ChannelHandlerContext context, Channel clientConnection, HttpExchangeStorage exchangeStorage) {
        this.clientConnectionContext = context;
        this.clientConnection = clientConnection;
        this.exchangeStorage = exchangeStorage;
    }

    @Override
    public void messageReceived(ChannelHandlerContext context, MessageEvent event) throws Exception {
        HttpResponse response = (HttpResponse) event.getMessage();
        HttpRequest request = (HttpRequest) clientConnectionContext.getAttachment();
        clientConnectionContext.setAttachment(new HttpExchange(request, response));
        
        clientConnection.write(response);
        
        Channel serverConnection = event.getChannel();
        close(serverConnection);
    }

    @Override
    public void channelClosed(ChannelHandlerContext context, ChannelStateEvent event) throws Exception {
        HttpExchange exchange = (HttpExchange) clientConnectionContext.getAttachment();
        exchangeStorage.store(exchange);
        close(clientConnection);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext context, ExceptionEvent event) throws Exception {
        log.error("unexpected exception caught on server handler, closing connection", event.getCause());
        Channel serverConnection = event.getChannel();
        close(serverConnection);
    }
    
    private void close(Channel channel) {
        if (channel != null && channel.isOpen() && channel.isConnected()) {
            channel.write(ChannelBuffers.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
        }
    }
}